package com.mini.grpc.server;

import com.mini.grpc.common.Metadata;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 服务端拦截器工具类
 * 提供创建和组合拦截器的工具方法
 * 
 * @author Mini-gRPC
 */
public final class ServerInterceptors {
    
    private ServerInterceptors() {
        // 工具类，不允许实例化
    }
    
    /**
     * 为服务定义添加拦截器
     * 
     * @param service 原始服务定义
     * @param interceptors 拦截器列表
     * @return 包含拦截器的新服务定义
     */
    public static ServerServiceDefinition intercept(ServerServiceDefinition service, 
                                                   ServerInterceptor... interceptors) {
        return intercept(service, Arrays.asList(interceptors));
    }
    
    /**
     * 为服务定义添加拦截器
     * 
     * @param service 原始服务定义
     * @param interceptors 拦截器列表
     * @return 包含拦截器的新服务定义
     */
    public static ServerServiceDefinition intercept(ServerServiceDefinition service, 
                                                   List<ServerInterceptor> interceptors) {
        if (interceptors == null || interceptors.isEmpty()) {
            return service;
        }
        
        ServerServiceDefinition.Builder builder = ServerServiceDefinition.builder(service.getServiceName());
        
        for (ServerMethodDefinition<?, ?> method : service.getMethods().values()) {
            @SuppressWarnings("unchecked")
            ServerMethodDefinition<Object, Object> typedMethod = (ServerMethodDefinition<Object, Object>) method;
            ServerMethodDefinition<Object, Object> interceptedMethod = intercept(typedMethod, interceptors);
            @SuppressWarnings("unchecked")
            com.mini.grpc.common.MethodDescriptor<Object, Object> typedDescriptor = 
                (com.mini.grpc.common.MethodDescriptor<Object, Object>) interceptedMethod.getMethodDescriptor();
            @SuppressWarnings("unchecked")
            ServerCallHandler<Object, Object> typedHandler = 
                (ServerCallHandler<Object, Object>) interceptedMethod.getServerCallHandler();
            builder.addMethod(typedDescriptor, typedHandler);
        }
        
        return builder.build();
    }
    
    /**
     * 为可绑定服务添加拦截器
     * 
     * @param bindableService 可绑定服务
     * @param interceptors 拦截器列表
     * @return 包含拦截器的服务定义
     */
    public static ServerServiceDefinition intercept(BindableService bindableService, 
                                                   ServerInterceptor... interceptors) {
        return intercept(bindableService.bindService(), interceptors);
    }
    
    /**
     * 为方法定义添加拦截器
     * 
     * @param method 原始方法定义
     * @param interceptors 拦截器列表
     * @param <ReqT> 请求类型
     * @param <RespT> 响应类型
     * @return 包含拦截器的新方法定义
     */
    @SuppressWarnings("unchecked")
    private static <ReqT, RespT> ServerMethodDefinition<ReqT, RespT> intercept(
            ServerMethodDefinition<?, ?> method, 
            List<ServerInterceptor> interceptors) {
        
        ServerMethodDefinition<ReqT, RespT> typedMethod = (ServerMethodDefinition<ReqT, RespT>) method;
        ServerCallHandler<ReqT, RespT> handler = typedMethod.getServerCallHandler();
        
        // 从后往前应用拦截器，这样第一个拦截器会最先执行
        for (int i = interceptors.size() - 1; i >= 0; i--) {
            handler = wrapHandler(interceptors.get(i), handler);
        }
        
        return typedMethod.withServerCallHandler(handler);
    }
    
    /**
     * 包装处理器以应用拦截器
     * 
     * @param interceptor 拦截器
     * @param handler 原始处理器
     * @param <ReqT> 请求类型
     * @param <RespT> 响应类型
     * @return 包装后的处理器
     */
    private static <ReqT, RespT> ServerCallHandler<ReqT, RespT> wrapHandler(
            ServerInterceptor interceptor,
            ServerCallHandler<ReqT, RespT> handler) {
        
        return new ServerCallHandler<ReqT, RespT>() {
            @Override
            public ServerCall.Listener<ReqT> startCall(ServerCall<ReqT, RespT> call, Metadata headers) {
                return interceptor.interceptCall(call, headers, handler);
            }
        };
    }
    
    /**
     * 创建拦截调用的包装器
     * 
     * @param call 原始调用
     * @param interceptor 拦截器
     * @param <ReqT> 请求类型
     * @param <RespT> 响应类型
     * @return 包装后的调用
     */
    public static <ReqT, RespT> ServerCall<ReqT, RespT> interceptCall(
            ServerCall<ReqT, RespT> call,
            ServerInterceptor interceptor) {
        
        return new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
            // 可以在这里添加额外的拦截逻辑
        };
    }
    
    /**
     * 转发服务端调用的抽象类
     * 用于创建调用包装器
     */
    public abstract static class ForwardingServerCall<ReqT, RespT> extends ServerCall<ReqT, RespT> {
        
        /**
         * 获取被委托的调用
         * 
         * @return 被委托的调用
         */
        protected abstract ServerCall<ReqT, RespT> delegate();
        
        @Override
        public void request(int numMessages) {
            delegate().request(numMessages);
        }
        
        @Override
        public void sendHeaders(Metadata headers) {
            delegate().sendHeaders(headers);
        }
        
        @Override
        public void sendMessage(RespT message) {
            delegate().sendMessage(message);
        }
        
        @Override
        public void close(com.mini.grpc.common.Status status, Metadata trailers) {
            delegate().close(status, trailers);
        }
        
        @Override
        public boolean isCancelled() {
            return delegate().isCancelled();
        }
        
        @Override
        public com.mini.grpc.common.MethodDescriptor<ReqT, RespT> getMethodDescriptor() {
            return delegate().getMethodDescriptor();
        }
        
        /**
         * 简单转发服务端调用实现
         */
        public abstract static class SimpleForwardingServerCall<ReqT, RespT> extends ForwardingServerCall<ReqT, RespT> {
            private final ServerCall<ReqT, RespT> delegate;
            
            protected SimpleForwardingServerCall(ServerCall<ReqT, RespT> delegate) {
                this.delegate = delegate;
            }
            
            @Override
            protected ServerCall<ReqT, RespT> delegate() {
                return delegate;
            }
        }
    }
} 